package pers.xiaojun.boot.module.system.service.dict;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pers.xiaojun.boot.mybatis.core.convert.PageConvert;
import pers.xiaojun.boot.common.exception.BusinessException;
import pers.xiaojun.boot.common.util.CollectionUtils;
import pers.xiaojun.boot.module.system.controller.dict.vo.type.DictTypeQueryReqVO;
import pers.xiaojun.boot.module.system.controller.dict.vo.type.DictTypeSaveReqVO;
import pers.xiaojun.boot.module.system.dao.entity.dict.DictTypeDO;
import pers.xiaojun.boot.module.system.dao.mapper.dict.DictTypeMapper;
import pers.xiaojun.boot.mybatis.core.query.LambdaQueryWrapperX;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static pers.xiaojun.boot.module.system.constants.BusinessCodeConstants.*;

/**
 * 字典类型服务类实现
 *
 * @author xiaojun
 * @since 2025-11-05
 */
@Service
public class DictTypeServiceImpl extends ServiceImpl<DictTypeMapper, DictTypeDO> implements DictTypeService {

    @Lazy
    @Autowired
    private DictDataService dictDataService;

    @Override
    public DictTypeDO saveDictType(DictTypeSaveReqVO saveVO) {
        validateDictTypeBasicInfo(null, saveVO.getName(), saveVO.getType());

        DictTypeDO dictType = BeanUtil.toBean(saveVO, DictTypeDO.class);
        this.baseMapper.insert(dictType);
        return dictType;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DictTypeDO updateDictType(DictTypeSaveReqVO updateVO) {
        // 字典类型无法更新，进行置空
        updateVO.setType(null);

        validateDictTypeExists(updateVO.getId());
        validateDictTypeBasicInfo(updateVO.getId(), updateVO.getName(), null);

        DictTypeDO dictType = BeanUtil.toBean(updateVO, DictTypeDO.class);
        this.baseMapper.updateById(dictType);

        return dictType;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeDictTypeById(Long dictId) {
        DictTypeDO dictType = validateDictTypeExists(dictId);

        this.baseMapper.deleteById(dictId);

        // 删除字典数据
        dictDataService.removeDictDataByDictType(dictType.getType());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeDictTypeByIds(List<Long> dictIds) {
        List<DictTypeDO> dictTypes = this.baseMapper.selectByIds(dictIds);

        if (dictTypes.size() != dictIds.size()) {
            Set<Long> notFindIds = Sets.difference(
                    new HashSet<>(dictIds),
                    CollectionUtils.convertSet(dictTypes, DictTypeDO::getId)
            );
            throw new BusinessException(DICT_NOT_EXISTS.getCode(), StrUtil.format("字典Id:{}不存在", notFindIds));
        }
        // 删除字典数据
        this.baseMapper.deleteByIds(dictIds);

        dictDataService.removeDictDataByDictTypes(CollectionUtils.convertList(dictTypes, DictTypeDO::getType));
    }

    @Override
    public DictTypeDO getDeptTypeById(Long deptId) {
        return validateDictTypeExists(deptId);
    }

    @Override
    public Page<DictTypeDO> listDictTypesPage(DictTypeQueryReqVO queryVO) {
        return this.baseMapper.selectPage(PageConvert.INSTANCE.toPage(queryVO), new LambdaQueryWrapperX<DictTypeDO>()
                .likeIfPresent(DictTypeDO::getName, queryVO.getName())
                .likeIfPresent(DictTypeDO::getType, queryVO.getType())
                .eqIfPresent(DictTypeDO::getStatus, queryVO.getStatus())
                .betweenIfPresent(DictTypeDO::getCreateTime, queryVO.getCreateTime())
        );
    }

    @Override
    public DictTypeDO validateDictTypeExists(String DictType) {
        DictTypeDO dictType = this.baseMapper.selectByType(DictType);
        if (dictType == null) {
            throw new BusinessException(DICT_TYPE_NOT_EXISTS);
        }
        return dictType;
    }


    /**
     * 校验字典基础信息
     *
     * @param id   字典Id
     * @param name 字典名称
     * @param type 字典类型
     */
    public void validateDictTypeBasicInfo(Long id, String name, String type) {
        DictTypeDO dictType = this.baseMapper.selectByName(name);
        if (dictType != null && !dictType.getId().equals(id)) {
            throw new BusinessException(DICT_NAME_EXISTS);
        }

        dictType = this.baseMapper.selectByType(type);
        if (dictType != null && !dictType.getId().equals(id)) {
            throw new BusinessException(DICT_TYPE_EXISTS);
        }
    }

    /**
     * 校验字典是否存在
     *
     * @param id 字典Id
     * @return 字典
     */
    private DictTypeDO validateDictTypeExists(Long id) {
        DictTypeDO dictType = this.baseMapper.selectById(id);
        if (dictType == null) {
            throw new BusinessException(DICT_NOT_EXISTS);
        }
        return dictType;
    }
}
